
use std::ops::*;
use std::sync::Arc;

use crate::vec::*;
use crate::ray::Ray;

use crate::object::material::Material;

pub trait Hittable {
    fn hit(&self, r: &Ray, t_min: f32, t_max:f32, rec: &mut HitRecord) -> bool;
}


pub struct HitRecord {
    pub p: Point3,
    pub normal: Vec3,
    pub t: f32,
    pub front_face: bool,
    pub mat_ptr: Option<Arc<dyn Material>>,
}

impl Default for HitRecord {
    fn default() -> Self {
        Self {
            p: Point3::default(),
            normal: Vec3::default(),
            t: f32::default(),
            front_face: false,
            mat_ptr: None,
        }
    }
}

impl HitRecord {
    
    pub fn set_point(&mut self, pt: Point3) -> &mut Self {
        self.p = pt;
        self
    }

    pub fn get_point(&self) -> Point3 {
        self.p.clone()
    }

    pub fn set_normal(&mut self, n: Vec3) -> &mut Self {
        self.normal = n;
        self
    }


    pub fn get_normal(&self) -> Vec3 {
        self.normal.clone()
    }

    pub fn set_t(&mut self, t:f32) -> &mut Self {
        self.t = t;
        self
    }

    pub fn get_t(&self) -> f32 {
        self.t.clone()
    }

    pub fn set_face_normal(&mut self, r: &Ray, outward_normal: &Vec3) {
        if r.direction().dot(&outward_normal) < 0.0 { //
            self.front_face = true;
            self.normal = *outward_normal;
        } else {
            self.front_face = false;
            self.normal = - *outward_normal;
        }
    }
}
